package lol.clann.bukkit.pluginboot.model.rawmessage;

import lol.clann.bukkit.pluginboot.util.ChatSerializerUtils;
import lol.clann.bukkit.pluginboot.util.PacketUtils;
import lol.clann.bukkit.pluginboot.util.PlayerUtils;
import lol.clann.clannboot.annotation.inject.Inject;
import lol.clann.clannboot.annotation.inject.PostInject;
import lol.clann.clannboot.annotation.svc.Service;
import lol.clann.clannboot.util.clazz.*;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import lombok.SneakyThrows;
import org.bukkit.ChatColor;

import java.lang.reflect.Constructor;

/**
 * @author pyz
 * @date 2018/8/18 上午10:41
 */
@Service(priority = Integer.MAX_VALUE)
class RawMessaeUtils {

    public static final WrapClass classChatComponentText = ClassUtils.forName("{nms}.ChatComponentText");

    static final BiMap<ChatColor, String> stylesToNames;

    static {
        ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
        for (final ChatColor style : ChatColor.values()) {
            if (!style.isFormat()) {
                continue;
            }

            String styleName;
            switch (style) {
                case MAGIC:
                    styleName = "obfuscated";
                    break;
                case UNDERLINE:
                    styleName = "underlined";
                    break;
                default:
                    styleName = style.name().toLowerCase();
                    break;
            }

            builder.put(style, styleName);
        }
        stylesToNames = builder.build();
    }

    public Constructor<?> chatComponentText;
    public WrapField chatType;
    public WrapField chatComponent;
    private boolean simple;
    private WrapClass classChatMessageType;
    @Inject
    private PlayerUtils playerUtils;
    @Inject
    private ChatSerializerUtils chatSerializerUtils;

    @PostInject
    private void PostInject() {
        chatComponentText = classChatComponentText.getConstructor(ParameterCondition.of(String.class));
        chatComponent = PacketUtils.classPacketPlayOutChat.getField(FieldFilter.build().type(ChatSerializerUtils.classIChatBaseComponent));

        try {
            // 高版本
            classChatMessageType = ClassUtils.forName("{nms}.ChatMessageType");
            chatType = PacketUtils.classPacketPlayOutChat.getField(FieldFilter.build().type(classChatMessageType));
            simple = false;
        } catch (Throwable e) {
            // 1.7
            simple = true;
            chatType = PacketUtils.classPacketPlayOutChat.getField(FieldFilter.build().type(boolean.class).index(0));
        }
    }

    Object createTextPacket(String message) {
        try {
            Object packet = PacketUtils.classPacketPlayOutChat.newInstance();
            chatComponent.set(packet, fromJson(message));
            if (simple) {
                chatType.set(packet, true);
            } else {
                Object type = Enum.valueOf(classChatMessageType.getHandle(), "SYSTEM");
                // ChatMessageType.SYSTEM
                chatType.set(packet, type);
            }
            return packet;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * Creates a ChatComponentText from plain text
     *
     * @param message The text to convert to a chat component
     * @return The chat component
     */
    @SneakyThrows
    Object componentText(String message) {
        return chatComponentText.newInstance(message);
    }

    /**
     * Attempts to convert a String representing a JSON message into a usable object
     *
     * @param json The JSON to attempt to parse
     * @return The object representing the text in JSON form, or <code>null</code> if something went wrong converting the String to JSON data
     */
    Object fromJson(String json) {
        if (!json.trim().startsWith("{")) {
            return componentText(json);
        }
        return chatSerializerUtils.deserialize(json);
    }

}
